package com.woniuxy.shiro.config;

import org.apache.shiro.mgt.SessionStorageEvaluator;
import org.apache.shiro.spring.LifecycleBeanPostProcessor;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.mgt.DefaultWebSessionStorageEvaluator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.servlet.Filter;
import java.util.HashMap;
import java.util.Map;

/**
 * shiro的核心配置类，我们要完成SecurityManager的配置，类似之前基于ini配置文件
 */
@Configuration
public class ShiroConfig {
    //<bean id="sessionStorageEvaluator" class ="SessionStorageEvaluator的类路径" />

    /**
     * 禁用session, 不保存用户登录状态。保证每次请求都重新认证。
     * 需要注意的是，如果用户代码里调用Subject.getSession()还是可以用session
     */
    @Bean
    protected SessionStorageEvaluator sessionStorageEvaluator() {
        DefaultWebSessionStorageEvaluator sessionStorageEvaluator = new DefaultWebSessionStorageEvaluator();
        sessionStorageEvaluator.setSessionStorageEnabled(false);
        return sessionStorageEvaluator;
    }
    /**
     * 配置安全管理器 SecurityManager  注入我们的自定义域
     */
    @Bean
    public DefaultWebSecurityManager securityManager(MyRealm mrRealm){
        //new出默认的安全管理器
        DefaultWebSecurityManager defaultWebSecurityManager = new DefaultWebSecurityManager();
        //放入自定义的域 让它生效
        defaultWebSecurityManager.setRealm(mrRealm);
        return defaultWebSecurityManager;
    }
    /**
     * 配置我们的过滤器：
     */
    @Bean("shiroFilterFactoryBean")//等会可能会报错
    public ShiroFilterFactoryBean shiroFilter(DefaultWebSecurityManager defaultSecurityManager){
        //1.创建shiro的过滤器工厂
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        //2.设置必备属性 安全管理器
        shiroFilterFactoryBean.setSecurityManager(defaultSecurityManager);
        //这个key 表示别名
        Map<String, Filter> filters = new HashMap<>();
        //3.放入我们自定义的过滤器 并且 shiroFilter会被当做别名  shiro底层会根据这个别名来进行判断 url过滤规则
        filters.put("shiroFilter",new ShiroFilter());
        //4.再把自定义的Map 一堆过滤器，放入shiro的过滤器工厂中
        shiroFilterFactoryBean.setFilters(filters);
        Map<String, String> filterChainDefinitionMap = new HashMap<>();
        //key是拦截的请求类型  value是我们定义的过滤器的名字
        filterChainDefinitionMap.put("/**","shiroFilter");
        //登录请求 让它匿名访问 就是不用登录也可以方法
        filterChainDefinitionMap.put("/auth/login","anon");
        filterChainDefinitionMap.put("/401","anon");
        //最后一步：让你的过滤器选择过滤什么请求 比如 /  还是 /login

        //下面是放行swagger-ui.html的
        filterChainDefinitionMap.put("/swagger-ui.html", "anon");
        filterChainDefinitionMap.put("/swagger-resources", "anon");
        filterChainDefinitionMap.put("/swagger-resources/configuration/security", "anon");
        filterChainDefinitionMap.put("/swagger-resources/configuration/ui", "anon");
        filterChainDefinitionMap.put("/v2/api-docs", "anon");
        filterChainDefinitionMap.put("/webjars/springfox-swagger-ui/**", "anon");
        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
        return shiroFilterFactoryBean;
    }
    //开启shiro的注解支持 我们后面要用注解
    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(DefaultWebSecurityManager defaultSecurityManager){
        AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor =
                new AuthorizationAttributeSourceAdvisor();
        authorizationAttributeSourceAdvisor.setSecurityManager(defaultSecurityManager);
        return authorizationAttributeSourceAdvisor;
    }

    /**
     * 管理subject主体对象的生命周期组件
     * @return
     */
    @Bean("lifecycleBeanPostProcessor")
    public LifecycleBeanPostProcessor getLifecycleBeanPostProcessor() {
        return new LifecycleBeanPostProcessor();
    }
}